#include<stdio.h> 
#include<stdlib.h>
#include<sys/types.h> 
#include<sys/stat.h> 
#include<fcntl.h> 
#include<unistd.h> 
#include<linux/input.h>
#include <sys/mman.h> 

#define LCD_Length 800  
#define LCD_Width 380

typedef struct ListNode
{
	int fd;
    int length;
    int width;
	struct ListNode* prev;
	struct ListNode* next;
} LinkList;


/******** 全局变量定义区 ********/

struct input_event touch; 
int touch_fd , lcd_fd , photo_fd_1 , photo_fd_2 , photo_fd_3 , photo_fd_4 , photo_fd_delete , photo_fd_bottom , fifo_fd; 
int touch_x , touch_y; 
LinkList* firstNode;
LinkList* currentNode;
LinkList* deleteNode;
LinkList* currentNode_delete;

/******** 全局变量定义区 ********/

// 从设备文件读取相应的触摸屏信息 read 
void get_touch() 
{ 
 
 // sizeof() ---> 可以用于获得结构体类型大小 
 read(touch_fd,&touch,sizeof(touch)); 

 // 3. 进一步的处理 
 if( touch.type == EV_ABS && touch.code == ABS_X ) touch_x = touch.value*800/1024; 
 if( touch.type == EV_ABS && touch.code == ABS_Y ) touch_y = touch.value*480/600; 
} 

// 触摸屏动作识别，返回识别到的触摸屏动作 
int get_touch_event() 
{ 
    int tmp_touch_x = 0; // 此变量用于记录起始坐标值 
    int tmp_touch_y = 0; 

    int event_flags = -1; // 触摸屏动作标志位 

    while(1) 
    { 
        get_touch(); // 获取触摸屏信息，以及X，Y决定坐标事件处理 


        if( touch.type == EV_KEY && touch.code == BTN_TOUCH && touch.value > 0) 
        { 
            printf("手指按下触摸屏\n");

                tmp_touch_x = touch_x; // 保存起始坐标值 
                tmp_touch_y = touch_y; 
                 
        } 


        if( touch.type == EV_KEY && touch.code == BTN_TOUCH && touch.value == 0)  // 手指离开触摸屏
        { 

            printf("手指松开触摸屏\n");

            event_flags = 0; // 单击动作 
            if( tmp_touch_x - touch_x > 100 ) event_flags = 1; // 左划动作 
            if( touch_x - tmp_touch_x > 100 ) event_flags = 2; // 右划动作
            if( tmp_touch_y - touch_y > 100 ) event_flags = 3; // 上划动作
            if( touch_y - tmp_touch_y > 100 ) event_flags = 4; // 下划动作
            if(touch_x >= 0 && touch_x < 100 && touch_y >= 380 && touch_y < 480) event_flags = 5; //点击左下角
            if(touch_x >= 700 && touch_x < 800 && touch_y >= 380 && touch_y < 480) event_flags = 6; //点击右下角
            if(touch_x >= 150 && touch_x < 250 && touch_y >= 380 && touch_y < 480) event_flags = 7; //永久删除图片
            if(touch_x >= 250 && touch_x < 350 && touch_y >= 380 && touch_y < 480) event_flags = 8; //删除图片
            if(touch_x >= 350 && touch_x < 450 && touch_y >= 380 && touch_y < 480) event_flags = 9; //进入回收站
            if(touch_x >= 450 && touch_x < 550 && touch_y >= 380 && touch_y < 480) event_flags = 10; //恢复图片
            if(touch_x >= 550 && touch_x < 650 && touch_y >= 380 && touch_y < 480) event_flags = 11; //退出

            return event_flags; // 返回触摸屏动作标志位 
        } 
    } 
} 

//内存空间初始化
LinkList* photo_init()
{
    //动态申请内存空间
    LinkList* newNode_1 = (LinkList*)malloc(sizeof(LinkList));
    LinkList* newNode_2 = (LinkList*)malloc(sizeof(LinkList));
    LinkList* newNode_3 = (LinkList*)malloc(sizeof(LinkList));
    LinkList* newNode_4 = (LinkList*)malloc(sizeof(LinkList));
    deleteNode = (LinkList*)malloc(sizeof(LinkList));

    if(newNode_1 == NULL || newNode_2 == NULL || newNode_3 == NULL || newNode_4 == NULL)
	{
		printf("分配内存失败\n");
		exit(-1);
	}

    newNode_1->next = newNode_2;
    newNode_1->prev = newNode_4;
    newNode_1->fd = photo_fd_1;
    newNode_1->length = 372;
    newNode_1->width = 270;

    newNode_2->next = newNode_3;
    newNode_2->prev = newNode_1;
    newNode_2->fd = photo_fd_2;
    newNode_2->length = 424;
    newNode_2->width = 270;

    newNode_3->next = newNode_4;
    newNode_3->prev = newNode_2;
    newNode_3->fd = photo_fd_3;
    newNode_3->length = 447;
    newNode_3->width = 279;

    newNode_4->next = newNode_1;
    newNode_4->prev = newNode_3;
    newNode_4->fd = photo_fd_4;
    newNode_4->length = 468;
    newNode_4->width = 266;

    deleteNode->next = NULL;
    deleteNode->prev = NULL;
    deleteNode->fd = photo_fd_delete;
    deleteNode->length = 800;
    deleteNode->width = 480;

    return newNode_1;

}

//删除链表控制
void delete_Node(LinkList* Node)
{

    Node -> prev -> next = Node -> next; //将结点从相册链表中删除
    Node -> next ->prev = Node -> prev;

    if(deleteNode -> prev != NULL)
    {
        // temp = deleteNode -> prev; //将删除的结点插入删除链表尾部
        // temp -> next = Node;
        // Node -> prev = temp;

        //指向最后一个结点
        deleteNode -> prev->next = Node;
        Node->prev = deleteNode -> prev;
        Node->next = deleteNode->next;
        deleteNode->next->prev = Node;
        deleteNode->prev = Node;

    }
    else
    {
        // Node -> prev = deleteNode;
        // deleteNode -> next = Node;
        deleteNode->prev = Node;
        deleteNode->next = Node;
        Node -> next = deleteNode->prev;
        Node ->prev = deleteNode->next;
    }
    
}

//页面渲染控制
void bmp_mmap(LinkList * Node)
{
    int * mmap_star = mmap(NULL,LCD_Length*LCD_Width*4,PROT_READ | PROT_WRITE,MAP_SHARED,lcd_fd,0); 

    if(mmap_star == MAP_FAILED) 
    { 
        printf("映射失败！\n"); 
        return; 
    } 

     off_t lseek_ret = lseek(Node->fd,54,SEEK_SET);//跳过开头54个字节

    int swallow = Node->length % 4;
    char buf[Node->length * Node->width * 3];
    int skip_y;
    for(skip_y = 0;skip_y<Node->width;skip_y++)
    {
        char * addr = buf + skip_y * Node->length * 3;
        read(Node->fd,addr,Node->length*3);
        lseek(Node->fd,swallow,SEEK_CUR);
    }
    //if(read_ret == -1){printf("读取bmp失败\n"); return ;}

    int x , y;  
    int n = 0;
    for(y=0;y<LCD_Width;y++) 
    { 
        for(x=0;x<LCD_Length;x++) 
        {   
            if(x >= (LCD_Length/2 - Node->length/2) && x < (LCD_Length/2 - (Node->length)/2 + Node->length) && y >= (LCD_Width/2 - Node->width/2) && y < (LCD_Width/2 - Node->width/2 + Node->width))
            {
                *(mmap_star + LCD_Length*(LCD_Width-1-y)+x) = buf[3*n] + (buf[3*n+1]<<8) + (buf[3*n+2] <<16);
                n++;
            }
                
            else
            {
                *(mmap_star + LCD_Length*(LCD_Width-1-y)+x) = 0x00000000;
            }
 
        } 
    } 

    munmap(mmap_star,LCD_Length*LCD_Width*4);

}

//底部按钮渲染
void bottom_init()
{ 
    int * mmap_star = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED,lcd_fd,0); 

    if(mmap_star == MAP_FAILED) 
    { 
    printf("映射失败！\n"); 
    return ; 
    } 

    off_t lseek_ret = lseek(photo_fd_bottom,54,SEEK_SET);//跳过开头54个字节

    char rgb[800*100*3]; 
    int read_ret = read(photo_fd_bottom,rgb,800*100*3); 


    int x; 
    int y; 
    for(y=0;y<100;y++) 
    { 
        for(x=0;x<800;x++) 
        { 
            *(mmap_star + 800*(479-y)+x) = rgb[3*(800*y+x)]<<0 | rgb[3*(800*y+x)+1]<<8 | rgb[3*(800*y+x)+2] <<16;

        } 
    } 

    munmap(mmap_star,480*800*4);

}

//主函数
int main() 
{ 
    /*******打开设备文件*******/

    touch_fd = open("/dev/input/event0",O_RDWR);
    lcd_fd = open("/dev/fb0",O_RDWR);
    photo_fd_1 = open("/a.bmp",O_RDWR);
    photo_fd_2 = open("/b.bmp",O_RDWR);
    photo_fd_3 = open("/c.bmp",O_RDWR);
    photo_fd_4 = open("/d.bmp",O_RDWR);
    photo_fd_delete = open("/surface.bmp",O_RDWR);
    photo_fd_bottom = open("/photo_bottom.bmp",O_RDWR);
    if(access("/my_fifo" , F_OK) )  mkfifo("/my_fifo",0777);
    fifo_fd = open("/my_fifo",O_RDWR);

    /*******打开设备文件*******/

    if(touch_fd == -1 || lcd_fd == -1 || photo_fd_1 == -1 || photo_fd_2 == -1 || photo_fd_3 == -1 || photo_fd_4 == -1) 
    { 
        printf("打开图片失败！\n"); 
        return -1; 
    } 

    bottom_init();
    firstNode = photo_init(); //获取图片循环链表表头
    currentNode = firstNode;
    bmp_mmap(firstNode);

    while(1) 
    { 

        int flag_x_y = get_touch_event();

        if(flag_x_y == 0) 
        { 
            printf("单击！\n"); 
        }  
        else if(flag_x_y == 1 || flag_x_y == 3 || flag_x_y == 6) 
        { 
            printf("下一张照片！\n");
            if(currentNode != NULL)
            {
                currentNode = currentNode->next;
                bmp_mmap(currentNode);
            }
            
        } 
        else if(flag_x_y == 2 || flag_x_y == 4 || flag_x_y == 5) 
        { 
            printf("上一张照片！\n");
            if(currentNode != NULL)
            {
                currentNode = currentNode->prev;
                bmp_mmap(currentNode); 
            }
            
        }
        else if(flag_x_y == 7) //永久删除图片
        {
            printf("永久删除图片\n");
            LinkList* temp = currentNode->next;

            if(currentNode != NULL)
            {
                currentNode -> prev -> next = currentNode -> next; //将结点从相册链表中删除
                currentNode -> next ->prev = currentNode -> prev;
            }
    
            if(temp == currentNode)
            {
                bmp_mmap(deleteNode);
                firstNode = NULL;
                currentNode = NULL;
            }
            else
            {
                bmp_mmap(temp);
                currentNode = currentNode ->next; 
            }

        } 
        else if(flag_x_y == 8) //删除照片
        {
            printf("删除图片\n");
            LinkList* temp = currentNode;

            if(currentNode != NULL)
            {
                if(temp == firstNode) firstNode = temp ->next;
                currentNode = currentNode -> next;
                delete_Node(temp);
            }
            
            if(currentNode == temp) 
            {
                bmp_mmap(deleteNode);
                firstNode = NULL;
                currentNode = NULL;
            }
            else 
            {
                bmp_mmap(currentNode);
            }
        }
        else if(flag_x_y == 9)
        {
            printf("进入回收站\n");
            if(deleteNode->next == NULL)
            {
                bmp_mmap(deleteNode);
            }else
            {
                currentNode_delete = deleteNode->next;
                bmp_mmap(currentNode_delete);
            }
            while(1)
            {
                int flag_x_y_2 = get_touch_event();

                if(flag_x_y_2 == 0) 
                { 
                    printf("单击回收站！\n"); 
                }  
                else if(flag_x_y_2 == 1 || flag_x_y_2 == 3 || flag_x_y_2 == 6) 
                { 
                    printf("回收站下一张照片！\n");
                    if(deleteNode -> next != NULL)
                    {
                        currentNode_delete = currentNode_delete->next;
                        bmp_mmap(currentNode_delete);
                    }
                    
                } 
                else if(flag_x_y_2 == 2 || flag_x_y_2 == 4 || flag_x_y_2 == 5) 
                { 
                    printf("回收站上一张照片！\n");
                    if(deleteNode -> prev != NULL)
                    {
                        currentNode_delete = currentNode_delete->prev;
                        bmp_mmap(currentNode_delete); 
                    }
                    
                }
                else if(flag_x_y_2 == 10)
                {
                    printf("恢复当前照片\n");

                    if(deleteNode -> next == NULL) //删除链表无结点
                    {
                        bmp_mmap(deleteNode);
                    }
                    else if(currentNode_delete -> next == currentNode_delete) //删除链表只有一个结点
                    {
                        LinkList* temp;
                        bmp_mmap(deleteNode);

                        temp = firstNode->prev;
                        firstNode->prev = currentNode_delete;
                        currentNode_delete->next = firstNode;
                        currentNode_delete->prev = temp;
                        temp->next = currentNode_delete;

                        deleteNode->prev = NULL;
                        deleteNode->next = NULL;
                        currentNode_delete = NULL;
                    }
                    else
                    {

                        LinkList* temp ;
                        LinkList* temp_2 = currentNode_delete -> next ;
                        
                        //temp = currentNode_delete->next;
                        bmp_mmap(currentNode_delete -> next);

                        
                        currentNode_delete->prev->next = currentNode_delete->next; //将恢复结点从删除链表删除
                        currentNode_delete->next->prev = currentNode_delete->prev;

                        if(deleteNode->next == currentNode_delete) //改变头部指针指向
                            deleteNode->next = currentNode_delete->next;
                        if(deleteNode->prev == currentNode_delete) //改变尾部指针指向
                            deleteNode->prev = currentNode_delete->prev;

                        if(firstNode == NULL) //给相册链表赋予第一个结点
                        {
                            firstNode = currentNode_delete;
                            firstNode->next = firstNode;
                            firstNode->prev = firstNode;
                            currentNode = firstNode;
                        }
                        else
                        {
                            temp = firstNode->prev;
                            firstNode->prev = currentNode_delete; //将删除结点添加到相册链表
                            currentNode_delete->next = firstNode;
                            currentNode_delete->prev = temp;
                            temp->next = currentNode_delete;

                        }
                        
                        currentNode_delete = temp_2;
                        //bmp_mmap(currentNode_delete);
                    }
                }
                else if(flag_x_y_2 == 11)
                {
                    printf("退出回收站\n");
                    bmp_mmap(currentNode);
                    break;
                } 

            }
        }
        else if(flag_x_y == 10)
        {
            printf("测试恢复坐标点\n");
        }
        else if(flag_x_y == 11) //退出相册
        {
            printf("退出相册\n");
           system("/mplayer -slave -input file=/my_fifo -zoom -x 800 -y 480 /mdata/video/bybe.avi &");;
            return 0;
        }

        
    } 



    close(touch_fd);
    close(lcd_fd);
    close(photo_fd_1);
    close(photo_fd_2);
    close(photo_fd_3);
    close(photo_fd_4); 

    return 0; 
}